package com.hujing.springsource.a02;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
public class TestBeanFactory {

    public static void main(String[] args) {
        //创建容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //将config的bean定义加入到容器中
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope("singleton").getBeanDefinition();
        beanFactory.registerBeanDefinition("config",beanDefinition);

        //给容器加入一些后处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        //执行加入的BeanFactory后处理器
        for (BeanFactoryPostProcessor processor : beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()) {
            processor.postProcessBeanFactory(beanFactory);
        }

        //执行加入的Bean后处理器
        for (BeanPostProcessor processor : beanFactory.getBeansOfType(BeanPostProcessor.class).values()) {
            //把处理器加入到beanFactory中
            beanFactory.addBeanPostProcessor(processor);
        }

        //打印容器中的beanDefinition
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        //初始化bean
        beanFactory.preInstantiateSingletons();

        System.out.println(">>>>>>>>>>>>>>>>>>>>>");

        //BeanFactory容器是在使用时才会初始化实例，如果要提前的话，就需要手动初始化beanFactory.preInstantiateSingletons();
        System.out.println(beanFactory.getBean(Bean1.class).getBean2());

    }

    @Configuration
    static class Config{
        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }
    }

    static class Bean1{
        public Bean1(){
//            log.info("Bean1的构造函数");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2(){
            return bean2;
        }
    }

    static class Bean2{
        public Bean2(){
//            log.info("Bean2的构造函数");
        }
    }
}
